package mylittleinvestigations.EasingFunctions;
import org.newdawn.slick.*;

public abstract class EasingFunction
{
    private double startValue;
    private double endValue;

    protected int msTotalDuration;
    protected int msElapsedDuration;

    public EasingFunction(double startValue, double endValue, int msDuration)
    {
        this.startValue = startValue;
        this.endValue = endValue;
        this.msTotalDuration = msDuration;

        this.Reset();
    }
    
    public int animationStartDelay;
    
    public int getAnimationStartDelay() { return this.animationStartDelay; }
    public void setAnimationStartDelay(int animationStartDelay) { this.animationStartDelay = animationStartDelay; }
    
    public boolean isStarted;
    
    public boolean getIsStarted() { return this.isStarted; }
    private void setIsStarted(boolean isStarted) { this.isStarted = isStarted; }
    
    public boolean isFinished;
    
    public boolean getIsFinished() { return this.isFinished; }
    private void setIsFinished(boolean isFinished) { this.isFinished = isFinished; }

    public void Begin()
    {
        this.Reset();
        this.setIsStarted(true);
    }

    public void Update(GameContainer gc, int delta)
    {
        if (this.getIsStarted() && !this.getIsFinished())
        {
            this.msElapsedDuration = Math.min(this.msElapsedDuration + delta, this.msTotalDuration + this.getAnimationStartDelay());

            if (this.msElapsedDuration - this.getAnimationStartDelay() == this.msTotalDuration)
            {
                this.setIsFinished(true);
            }
        }
    }

    public final void Reset()
    {
        this.msElapsedDuration = 0;
        this.setIsStarted(false);
        this.setIsFinished(false);
    }

    public void Finish()
    {
        this.msElapsedDuration = this.msTotalDuration + this.getAnimationStartDelay();
        this.setIsFinished(true);
    }

    public double GetCurrentValue()
    {
        if (this.msElapsedDuration < this.getAnimationStartDelay())
        {
            return this.startValue;
        }
        else if (this.msTotalDuration == 0)
        {
            return this.endValue;
        }
        else
        {
            return (this.startValue + (this.endValue - this.startValue) * GetNormalizedValue((double)(this.msElapsedDuration - this.getAnimationStartDelay()) / this.msTotalDuration));
        }
    }

    protected abstract double GetNormalizedValue(double normalizedTime);
}
